home *** CD-ROM | disk | FTP | other *** search
- /**************************************************************************
- *
- * Copyright (c) 1993 Silicon Graphics, Inc.
- * All Rights Reserved
- *
- * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF SGI
- *
- * The copyright notice above does not evidence any actual of intended
- * publication of such source code, and is an unpublished work by Silicon
- * Graphics, Inc. This material contains CONFIDENTIAL INFORMATION that is
- * the property of Silicon Graphics, Inc. Any use, duplication or
- * disclosure not specifically authorized by Silicon Graphics is strictly
- * prohibited.
- *
- * RESTRICTED RIGHTS LEGEND:
- *
- * Use, duplication or disclosure by the Government is subject to
- * restrictions as set forth in subdivision (c)(1)(ii) of the Rights in
- * Technical Data and Computer Software clause at DFARS 52.227-7013,
- * and/or in similar or successor clauses in the FAR, DOD or NASA FAR
- * Supplement. Unpublished - rights reserved under the Copyright Laws of
- * the United States. Contractor is SILICON GRAPHICS, INC., 2011 N.
- * Shoreline Blvd., Mountain View, CA 94039-7311
- **************************************************************************
- *
- * File: impOpen.c
- *
- * Description: Image file open routines.
- *
- **************************************************************************/
-
-
- #ident "$Revision: 1.8 $"
-
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <stdarg.h>
- #include <string.h>
- #include <assert.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <sys/mman.h>
- #include <fcntl.h>
- #include <unistd.h>
- #include <errno.h>
- #include <limits.h>
- #include "impI.h"
-
-
- /* Local functions */
-
- static IMPImage* openImage(int fd, const char *fname, void *buf,
- const char *mode, off_t offset, IMPCacheMode cache,
- uint_t rasterType, uint_t dimension,
- uint_t xSize, uint_t ySize,
- uint_t numChannels, uint_t imageType, char *name);
- static int initRLE(IMPImage *image, int fd, void *buf, const char *mode,
- off_t offset);
- static void errorCleanup(IMPImage *image, int fd, const char *fname);
- static int readData(int fd, void *fromBuf, void *toBuf,
- unsigned int amount, off_t offset);
- static int writeData(int fd, void *fromBuf, unsigned int amount, off_t offset);
- static void setCacheSize(IMPImage *image);
- static void getTags(IMPImage *image, int fd, void *buf, off_t offset,
- __uint32_t offsetTags);
-
-
- /**************************************************************************
- *
- * Function: impOpen
- *
- * Description: Opens an SGI image file specified by name for reading
- * or writing.
- *
- * Parameters:
- * fname (I) - name of the file to open
- * mode (I) - "r" for read-only, "w" for write-only. Note that
- * read-write mode is not currently supported.
- *
- * If the mode is "w" the following parameters must be specified.
- *
- * rasterType (I) - raster encoding and bytes per pixel code
- * (e.g. IMP_RASTER_VERBATIM1)
- * dimesnion (I) - image dimension. Set this to 1 for a colormap,
- * 2 for a bw image, and 3 for an rgb image.
- * xSize, ySize (I) - image size in pixels.
- * numChannels (I) - 1 for colormap or bw image, 3 for rgb.
- * imageType (I) - IMP_IMAGE_NORMAL for a regular image. See
- * imp.h for additional choices.
- * name (I) - optional image name. IMP_NAME_MAX characters maximum.
- * Specify as NULL for a default name string.
- *
- * Return: Pointer to an SGI image file handle if the open is successful.
- * NULL is returned and IMPerrno is set if the open fails.
- *
- **************************************************************************/
- /* VARARGS */
-
- IMPImage* impOpen(const char *fname, const char *mode, ...)
- {
- va_list ap;
- uint_t rasterType, dimension;
- uint_t xSize, ySize;
- uint_t numChannels, imageType;
- char *name;
-
- /*
- * Sanity check the inputs
- */
- assert(fname != NULL);
- assert(mode != NULL);
-
- /*
- * Get the arguments for the actual open function
- */
- if (*mode == 'w') {
- va_start(ap, mode);
- rasterType = va_arg(ap, uint_t);
- dimension = va_arg(ap, uint_t);
- xSize = va_arg(ap, uint_t);
- ySize = va_arg(ap, uint_t);
- numChannels = va_arg(ap, uint_t);
- imageType = va_arg(ap, uint_t);
- name = va_arg(ap, char*);
- va_end(ap);
- }
-
- /*
- * Call the actual open function
- */
- return (openImage(0, fname, NULL, mode, 0, IMPNoCache, rasterType,
- dimension, xSize, ySize, numChannels, imageType,
- name));
- }
-
-
- /**************************************************************************
- *
- * Function: impOpenFd
- *
- * Description: Opens an SGI image file specified by descriptor for reading
- * or writing.
- *
- * Parameters:
- * fd (I) - descriptor of the file.
- * mode (I) - "r" for read-only, "w" for write-only. Read-write
- * mode is not currently supported. Note that mode
- * must be compatible with the mode on fd.
- *
- * If the mode is "w" the following parameters must be specified.
- *
- * rasterType (I) - raster encoding and bytes per pixel code
- * (e.g. IMP_RASTER_VERBATIM1)
- * dimesnion (I) - image dimension. Set this to 1 for a colormap,
- * 2 for a bw image, and 3 for an rgb image.
- * xSize, ySize (I) - image size in pixels.
- * numChannels (I) - 1 for colormap or bw image, 3 for rgb.
- * imageType (I) - IMP_IMAGE_NORMAL for a regular image. See
- * imp.h for additional choices.
- * name (I) - optional image name. IMP_NAME_MAX characters maximum.
- * Specify as NULL for a default name string.
- *
- * Return: Pointer to an SGI image file handle if the open is successful.
- * NULL is returned and IMPerrno is set if the open fails.
- *
- **************************************************************************/
- /* VARARGS */
-
- IMPImage* impOpenFd(int fd, const char *mode, ...)
- {
- va_list ap;
- uint_t rasterType, dimension;
- uint_t xSize, ySize;
- uint_t numChannels, imageType;
- char *name;
- struct stat sbuf;
-
- /*
- * Sanity check the inputs
- */
- assert(mode != NULL);
-
- /*
- * Verify that the file descriptor is valid and
- * is seekable. To test seekability we check that an
- * lseek succeeds and that the descriptor is not connected
- * to a tty. It turns out that the lseek test succeeds for
- * a tty so we add the isatty test.
- */
- if (fstat(fd, &sbuf) < 0)
- _impReturnErrorPtr(IMP_ERR_BADFD);
- if (lseek(fd, 0L, SEEK_CUR) < 0 || isatty(fd))
- _impReturnErrorPtr(IMP_ERR_SEEK);
-
- /*
- * Get the arguments for the actual open function
- */
- if (*mode == 'w') {
- va_start(ap, mode);
- rasterType = va_arg(ap, uint_t);
- dimension = va_arg(ap, uint_t);
- xSize = va_arg(ap, uint_t);
- ySize = va_arg(ap, uint_t);
- numChannels = va_arg(ap, uint_t);
- imageType = va_arg(ap, uint_t);
- name = va_arg(ap, char*);
- va_end(ap);
- }
-
- /*
- * Call the actual open function
- */
- return (openImage(fd, NULL, NULL, mode, 0, IMPNoCache, rasterType,
- dimension, xSize, ySize, numChannels, imageType,
- name));
- }
-
-
- /**************************************************************************
- *
- * Function: impOpenBuf
- *
- * Description: Opens an SGI image file contained in a memory buffer for
- * reading or writing.
- *
- * The user must not deallocate the buffer until all libimp operations
- * are completed and impClose has been called.
- *
- * Parameters:
- * buf (I) - pointer to buffer hodling image
- * mode (I) - "r" for read-only, "w" for write-only. Read-write
- * mode is not currently supported. Note that mode
- * must be compatible with the mode on fd.
- *
- * If the mode is "w" the following parameters must be specified.
- *
- * rasterType (I) - raster encoding and bytes per pixel code
- * (e.g. IMP_RASTER_VERBATIM1)
- * dimesnion (I) - image dimension. Set this to 1 for a colormap,
- * 2 for a bw image, and 3 for an rgb image.
- * xSize, ySize (I) - image size in pixels.
- * numChannels (I) - 1 for colormap or bw image, 3 for rgb.
- * imageType (I) - IMP_IMAGE_NORMAL for a regular image. See
- * imp.h for additional choices.
- * name (I) - optional image name. IMP_NAME_MAX characters maximum.
- * Specify as NULL for a default name string.
- *
- * Return: Pointer to an SGI image file handle if the open is successful.
- * NULL is returned and IMPerrno is set if the open fails.
- *
- **************************************************************************/
- /* VARARGS */
-
- IMPImage* impOpenBuf(void *buf, const char *mode, ...)
- {
- uint_t rasterType, dimension;
- uint_t xSize, ySize;
- uint_t numChannels, imageType;
- char *name;
-
- /*
- * Sanity check the inputs
- */
- assert(buf != NULL);
- assert(mode != NULL);
-
- /*
- * Image write to a buffer not currently supported. This is because
- * it is not possible to know up front how big the buffer should be
- * before you write into it. This is due to RLE compressarion possibly
- * making the file larger than its dimensions would suggest.
- */
- if (*mode == 'w')
- _impReturnErrorPtr(IMP_ERR_NOWRITE);
-
- /*
- * Call the actual open function
- */
- return (openImage(0, NULL, buf, mode, 0, _IMPBufDirect, rasterType,
- dimension, xSize, ySize, numChannels, imageType,
- name));
- }
-
-
- /**************************************************************************
- *
- * Function: impOpenExt
- *
- * Description: Opens an SGI image file specified by name for reading
- * or writing. The Ext (extended) form of the impOpen function
- * allows an offset into the image file to be specified. In addition
- * the image may be cached in memory when in read-only mode.
- *
- * Parameters:
- * fname (I) - name of the file to open
- * mode (I) - "r" for read-only, "w" for write-only. Note that
- * read-write mode is not currently supported.
- * offset (I) - number of bytes from the start of the file where
- * reading or writing is to begin.
- * cache (I) - if IMPCache and mode is read-only, the entire image
- * will be cached in memory. If IMPNoCache or
- * mode is write-only, no caching is done.
- *
- * If the mode is "w" the following parameters must be specified.
- *
- * rasterType (I) - raster encoding and bytes per pixel code
- * (e.g. IMP_RASTER_VERBATIM1)
- * dimesnion (I) - image dimension. Set this to 1 for a colormap,
- * 2 for a bw image, and 3 for an rgb image.
- * xSize, ySize (I) - image size in pixels.
- * numChannels (I) - 1 for colormap or bw image, 3 for rgb.
- * imageType (I) - IMP_IMAGE_NORMAL for a regular image. See
- * imp.h for additional choices.
- * name (I) - optional image name. IMP_NAME_MAX characters maximum.
- * Specify as NULL for a default name string.
- *
- * Return: Pointer to an SGI image file handle if the open is successful.
- * NULL is returned and IMPerrno is set if the open fails.
- *
- **************************************************************************/
- /* VARARGS */
-
- IMPImage* impOpenExt(const char *fname, const char *mode, off_t offset,
- IMPCacheMode cache, ...)
- {
- va_list ap;
- uint_t rasterType, dimension;
- uint_t xSize, ySize;
- uint_t numChannels, imageType;
- char *name;
-
- /*
- * Sanity check the inputs
- */
- assert(fname != NULL);
- assert(mode != NULL);
-
- /*
- * Get the arguments for the actual open function
- */
- if (*mode == 'w') {
- va_start(ap, cache);
- rasterType = va_arg(ap, uint_t);
- dimension = va_arg(ap, uint_t);
- xSize = va_arg(ap, uint_t);
- ySize = va_arg(ap, uint_t);
- numChannels = va_arg(ap, uint_t);
- imageType = va_arg(ap, uint_t);
- name = va_arg(ap, char*);
- va_end(ap);
-
- /*
- * We do not do caching for image writes
- */
- cache = IMPNoCache;
- }
-
- /*
- * Call the actual open function
- */
- return (openImage(0, fname, NULL, mode, offset, cache, rasterType,
- dimension, xSize, ySize, numChannels, imageType,
- name));
- }
-
-
- /**************************************************************************
- *
- * Function: impOpenFdExt
- *
- * Description: Opens an SGI image file specified by descriptor for reading
- * or writing. The Ext (extended) form of the impOpenFd function
- * allows an offset into the image file to be specified. In addition
- * the image may be cached in memory when in read-only mode.
- *
- * Parameters:
- * fd (I) - descriptor of the file.
- * mode (I) - "r" for read-only, "w" for write-only. Read-write
- * mode is not currently supported. Note that mode
- * must be compatible with the mode on fd.
- * offset (I) - number of bytes from the start of the file where
- * reading or writing is to begin.
- * cache (I) - if IMPCache and mode is read-only, the entire image
- * will be cached in memory. If IMPNoCache or
- * mode is write-only, no caching is done.
- *
- * If the mode is "w" the following parameters must be specified.
- *
- * rasterType (I) - raster encoding and bytes per pixel code
- * (e.g. IMP_RASTER_VERBATIM1)
- * dimesnion (I) - image dimension. Set this to 1 for a colormap,
- * 2 for a bw image, and 3 for an rgb image.
- * xSize, ySize (I) - image size in pixels.
- * numChannels (I) - 1 for colormap or bw image, 3 for rgb.
- * imageType (I) - IMP_IMAGE_NORMAL for a regular image. See
- * imp.h for additional choices.
- * name (I) - optional image name. IMP_NAME_MAX characters maximum.
- * Specify as NULL for a default name string.
- *
- * Return: Pointer to an SGI image file handle if the open is successful.
- * NULL is returned and IMPerrno is set if the open fails.
- *
- **************************************************************************/
- /* VARARGS */
-
- IMPImage* impOpenFdExt(int fd, const char *mode, off_t offset,
- IMPCacheMode cache, ...)
- {
- va_list ap;
- uint_t rasterType, dimension;
- uint_t xSize, ySize;
- uint_t numChannels, imageType;
- char *name;
- struct stat sbuf;
-
- /*
- * Sanity check the inputs
- */
- assert(mode != NULL);
-
- /*
- * Verify that the file descriptor is valid and
- * is seekable. To test seekability we check that an
- * lseek succeeds and that the descriptor is not connected
- * to a tty. It turns out that the lseek test succeeds for
- * a tty so we add the isatty test.
- */
- if (fstat(fd, &sbuf) < 0)
- _impReturnErrorPtr(IMP_ERR_BADFD);
- if (lseek(fd, 0L, SEEK_CUR) < 0 || isatty(fd))
- _impReturnErrorPtr(IMP_ERR_SEEK);
-
- /*
- * Get the arguments for the actual open function
- */
- if (*mode == 'w') {
- va_start(ap, cache);
- rasterType = va_arg(ap, uint_t);
- dimension = va_arg(ap, uint_t);
- xSize = va_arg(ap, uint_t);
- ySize = va_arg(ap, uint_t);
- numChannels = va_arg(ap, uint_t);
- imageType = va_arg(ap, uint_t);
- name = va_arg(ap, char*);
- va_end(ap);
-
- /*
- * We do not do caching for image writes
- */
- cache = IMPNoCache;
- }
-
- /*
- * Call the actual open function
- */
- return (openImage(fd, NULL, NULL, mode, offset, cache, rasterType,
- dimension, xSize, ySize, numChannels, imageType,
- name));
- }
-
-
- /**************************************************************************
- *
- * Function: impOpenBufExt
- *
- * Description: Opens an SGI image file specified in a memory buffer for
- * reading or writing. The Ext (extended) form of the impOpenBuf function
- * allows an offset into the image file to be specified.
- *
- * The user must not deallocate the buffer until all libimp operations
- * are completed and impClose has been called.
- *
- * Parameters:
- * buf (I) - buffer containing the image
- * mode (I) - "r" for read-only, "w" for write-only. Read-write
- * mode is not currently supported. Note that mode
- * must be compatible with the mode on fd.
- * offset (I) - number of bytes from the start of the file where
- * reading or writing is to begin.
- *
- * If the mode is "w" the following parameters must be specified.
- *
- * rasterType (I) - raster encoding and bytes per pixel code
- * (e.g. IMP_RASTER_VERBATIM1)
- * dimesnion (I) - image dimension. Set this to 1 for a colormap,
- * 2 for a bw image, and 3 for an rgb image.
- * xSize, ySize (I) - image size in pixels.
- * numChannels (I) - 1 for colormap or bw image, 3 for rgb.
- * imageType (I) - IMP_IMAGE_NORMAL for a regular image. See
- * imp.h for additional choices.
- * name (I) - optional image name. IMP_NAME_MAX characters maximum.
- * Specify as NULL for a default name string.
- *
- * Return: Pointer to an SGI image file handle if the open is successful.
- * NULL is returned and IMPerrno is set if the open fails.
- *
- **************************************************************************/
- /* VARARGS */
-
- IMPImage* impOpenBufExt(void *buf, const char *mode, off_t offset, ...)
- {
- uint_t rasterType, dimension;
- uint_t xSize, ySize;
- uint_t numChannels, imageType;
- char *name;
-
- /*
- * Sanity check the inputs
- */
- assert(buf != NULL);
- assert(mode != NULL);
-
- /*
- * Image write to a buffer not currently supported. This is because
- * it is not possible to know up front how big the buffer should be
- * before you write into it. This is due to RLE compressarion possibly
- * making the file larger than its dimensions would suggest.
- */
- if (*mode == 'w')
- _impReturnErrorPtr(IMP_ERR_NOWRITE);
-
- /*
- * Call the actual open function
- */
- return (openImage(0, NULL, buf, mode, offset, _IMPBufDirect, rasterType,
- dimension, xSize, ySize, numChannels, imageType,
- name));
- }
-
-
- /*
- =========================================================================
- LOCAL FUNCTIONS
- =========================================================================
- */
-
-
- /**************************************************************************
- *
- * Function: openImage
- *
- * Description: Performs the actual job of opening an SGI Image file.
- * The file may be specified as either a filename or file
- * descriptor.
- *
- * Parameters:
- * fd (I) - descriptor of open file
- * fname (I) - name of the file to open. If NULL, fd or buf will be used.
- * buf (I) - buffer to open. If NULL, fd or fname will be used.
- * mode (I) - "r" for read-only, "w" for write-only. Note that if
- * fd is specified it must have permissions compatible
- * with mode.
- * offset (I) - offset into file to begin reading or writing.
- * cache (I) - if IMPCache and read-only, entire image is cached in
- * memory.
- *
- * The following are ignored if open is "r"
- *
- * rasterType (I) - raster encoding and bytes per pixel code
- * (e.g. IMP_RASTER_VERBATIM1)
- * dimension (I) - image dimension. Set this to 1 for a colormap,
- * 2 for a bw image, and 3 for an rgb image.
- * xSize, ySize (I) - image size in pixels.
- * numChannels (I) - 1 for colormap or bw image, 3 for rgb.
- * imageType (I) - IMP_IMAGE_NORMAL for a regular image. See
- * imp.h for additional choices.
- * name (I) - optional image name. IMP_NAME_MAX characters maximum.
- * Specify as NULL for a default name string.
- *
- * Return: Pointer to an SGI image file handle if the open is successful.
- * NULL is returned and IMPerrno is set if the open fails.
- *
- **************************************************************************/
-
- static IMPImage* openImage(int fd, const char *fname, void *buf,
- register const char *mode,
- off_t offset, IMPCacheMode cache,
- uint_t rasterType, uint_t dimension,
- uint_t xSize, uint_t ySize,
- uint_t numChannels, uint_t imageType, char *name)
- {
- register IMPImage *image;
- __uint32_t offsetTags;
-
- /*
- * Sanity check the mode setting
- */
- if (mode[1] == '+')
- _impReturnErrorPtr(IMP_ERR_READWRITE);
-
- /*
- * Allocate space for the header that we will return as the
- * image handle if all goes well.
- */
- if ((image = (IMPImage*)calloc(1, sizeof(IMPImage))) == NULL)
- _impReturnErrorPtr(IMP_ERR_MEMALLOC);
-
- /*
- * WRITE: If we are writing, we initialize and write the header
- */
- if (*mode == 'w') {
- /*
- * Create the file if necessary
- */
- if (fname)
- fd = creat(fname, 0666);
- if (fd < 0) {
- IMPerrno = errno;
- errorCleanup(image, fd, fname);
- _impReturnErrorPtr(IMPerrno);
- }
-
- /*
- * Initialize disk archived header fields and write the header
- */
- impMagic(image) = IMP_MAGIC;
- impRasterType(image) = (ushort_t)rasterType;
- impImageType(image) = imageType;
- impMinValue(image) = SHRT_MAX;
- impMaxValue(image) = SHRT_MIN;
- image->wastebytes = 0;
- image->dorev = 0;
- (void)strncpy(image->name, (name)? name: "no name", IMP_NAME_MAX);
- image->name[IMP_NAME_MAX - 1] = '\0';
- impXSize(image) = (ushort_t)xSize;
- impYSize(image) = 1;
- impNumChannels(image) = 1;
- if (dimension > 1)
- impYSize(image) = (ushort_t)ySize;
- if (dimension > 2)
- impNumChannels(image) = (ushort_t)numChannels;
- if (impNumChannels(image) == 1) {
- impDimension(image) = 2;
- if (impYSize(image) == 1)
- impDimension(image) = 1;
- } else
- impDimension(image) = 3;
- impTags(image) = (IMPTag *) NULL;
- if (writeData(fd, image, sizeof(IMPImage), offset) !=
- sizeof(IMPImage)) {
- IMPerrno = errno;
- errorCleanup(image, fd, fname);
- _impReturnErrorPtr(IMPerrno);
- }
- }
- /*
- * READ: If we are reading, we read the header and do sanity checks
- */
- else {
- int retv;
-
- /*
- * Open the file if necessary
- */
- if (buf == NULL) {
- if (fname)
- fd = open(fname, O_RDONLY);
- if (fd < 0) {
- IMPerrno = errno;
- errorCleanup(image, fd, fname);
- _impReturnErrorPtr(IMPerrno);
- }
- }
-
- /*
- * Read the image header. Note that we need to reinit the
- * pointers in the structure since reading the disk header
- * can change them from NULL.
- */
- retv = readData(fd, buf, image, sizeof(IMPImage), offset);
- image->tmpbuf = NULL;
- image->rowstart = NULL;
- image->rowsize = NULL;
- if (retv != sizeof(IMPImage)) {
- IMPerrno = errno;
- errorCleanup(image, fd, fname);
- _impReturnErrorPtr(IMPerrno);
- }
-
- /*
- * Determine if this image file needs byte swapping.
- * If it does, we need to swap the bytes of the disk
- * relevant portions of the header we just read.
- */
- if (_impSwapShort(impMagic(image)) == IMP_MAGIC) {
- image->dorev = 1;
- _impSwapHeader(image);
- } else
- image->dorev = 0;
-
- /*
- * Verify that this is an SGI Image file
- */
- if (impMagic(image) != IMP_MAGIC) {
- errorCleanup(image, fd, fname);
- _impReturnErrorPtr(IMP_ERR_BADMAGIC);
- }
- if (!impIsRLE(image) && !impIsVERBATIM(image)) {
- errorCleanup(image, fd, fname);
- _impReturnErrorPtr(IMP_ERR_BADRASTER);
- }
- if (impImageType(image) > IMP_IMAGE_COLORMAP) {
- errorCleanup(image, fd, fname);
- _impReturnErrorPtr(IMP_ERR_BADIMAGE);
- }
- }
-
- /*
- * Are there extension tags?
- */
- if(readData(fd, buf, &offsetTags, sizeof(__uint32_t),
- offset + IMP_TAG_PTR_OFFSET) == sizeof(__uint32_t)) {
- if(image->dorev)
- _impSwapLongs(&offsetTags, sizeof(long));
- if (offsetTags != 0)
- getTags(image, fd, buf, offset, offsetTags);
- }
-
-
- /*
- * If the raster encoding is RLE, there is some additional
- * processing
- */
- if (impIsRLE(image)) {
- if (initRLE(image, fd, buf, mode, offset) < 0) {
- errorCleanup(image, fd, fname);
- _impReturnErrorPtr(IMPerrno);
- }
- }
-
- /*
- * Allocate scratch storage for row operations
- */
- if ((image->tmpbuf = _impBufferAlloc(image)) == NULL) {
- errorCleanup(image, fd, fname);
- _impReturnErrorPtr(IMP_ERR_MEMALLOC);
- }
-
- /*
- * Initialize image header fields used in core
- */
- image->file = (buf) ? -1: fd;
- image->flags = (*mode == 'w') ? _IOWRT: _IOREAD;
- image->cnt = 0;
- image->ptr = NULL;
- image->base = NULL;
- image->x = image->y = image->z = 0;
- image->offset = offset + _IMP_TABLES_START;
- image->start = offset;
- image->cache = cache;
- image->cachebuf = NULL;
- image->cachesize = 0;
- image->cacheoffset = 0;
-
- /*
- * If we are performing image caching, set up the cache.
- * Otherwise prepare for disk based processing.
- */
- if (cache != IMPNoCache) {
- /*
- * We cache only the image data. This requires that we add an
- * offset when determining our position in the data since the cache
- * will not necessarily be aligned with the start of the file.
- */
- setCacheSize(image);
-
- /*
- * If we are heap caching, allocate space and read in the data
- */
- if (cache == IMPHeapCache) {
- if ((image->cachebuf = malloc(image->cachesize)) == NULL) {
- errorCleanup(image, fd, fname);
- _impReturnErrorPtr(IMP_ERR_MEMALLOC);
- }
- if (readData(image->file, buf, image->cachebuf, image->cachesize,
- image->cacheoffset) != image->cachesize) {
- IMPerrno = errno;
- free(image->cachebuf);
- errorCleanup(image, fd, fname);
- _impReturnErrorPtr(IMPerrno);
- }
- }
- /*
- * If we are memory mapping, simply do the mmap
- */
- else if (cache == IMPMapCache) {
- image->cachebuf = mmap(NULL, image->cachesize, PROT_READ,
- MAP_SHARED, image->file, image->cacheoffset);
- if (image->cachebuf == (void*)-1) {
- IMPerrno = errno;
- errorCleanup(image, fd, fname);
- _impReturnErrorPtr(IMPerrno);
- }
- }
- /*
- * If we have a user buffer we just point to that
- */
- else if (cache == _IMPBufDirect) {
- image->cachebuf = ((char*)buf) + image->cacheoffset;
- }
- }
- /*
- * Seek to start of image row table
- */
- else {
- if (lseek(image->file, image->offset, SEEK_SET) < 0) {
- IMPerrno = errno;
- errorCleanup(image, fd, fname);
- _impReturnErrorPtr(IMPerrno);
- }
- }
-
- return image;
- }
-
-
- /**************************************************************************
- *
- * Function: initRLE
- *
- * Description: Initializes the Run Length Encoding tables. We allocate
- * space for the tables. If we are writing the image, we initialize
- * the tables to known values. If we are reading the image, we seek
- * to the tables, read them and swap their bytes, if necessary.
- *
- * Parameters:
- * image (I) - pointer to an image structure
- * fd (I) - image file descriptor
- * buf (I) - image buffer
- * mode (I) - read/write flag
- * offset (I) - image start offset
- *
- * Return: 0 if successful. -1 if errors have been encountered. IMPerrno
- * will be set by this function if errors have occurred.
- *
- **************************************************************************/
-
- static int initRLE(IMPImage *image, int fd, void *buf,
- const char *mode, off_t offset)
- {
- int rleTableSize;
-
- /*
- * Allocate RLE location and size tables
- */
- rleTableSize = impYSize(image) * impNumChannels(image) * sizeof(__int32_t);
- image->rowstart = (__uint32_t*)malloc(rleTableSize);
- image->rowsize = (__int32_t*)malloc(rleTableSize);
- if (image->rowstart == NULL || image->rowsize == NULL)
- _impReturnError(IMP_ERR_MEMALLOC);
- image->rleend = _IMP_TABLES_START + (rleTableSize << 1);
-
- /*
- * WRITE: If we are writing, we initialize the tables
- */
- if (*mode == 'w') {
- register int nTable = rleTableSize / sizeof(__int32_t);
- register int i;
-
- for (i = 0; i < nTable; i++) {
- image->rowstart[i] = 0;
- image->rowsize[i] = -1;
- }
- }
- /*
- * READ: If we are reading, read the tables and swap bytes
- * if necessary.
- */
- else {
- if (readData(fd, buf, image->rowstart, rleTableSize,
- offset + _IMP_TABLES_START) != rleTableSize)
- _impReturnError(errno);
- if (readData(fd, buf, image->rowsize, rleTableSize,
- offset + _IMP_TABLES_START + rleTableSize)
- != rleTableSize)
- _impReturnError(errno);
- if (image->dorev) {
- _impSwapLongs(image->rowstart, rleTableSize);
- _impSwapLongs((__uint32_t*)image->rowsize, rleTableSize);
- }
- }
-
- return 0;
- }
-
-
- /**************************************************************************
- *
- * Function: errorCleanup
- *
- * Description: Ensures that we deallocate storage before we return due
- * to an error condition.
- *
- * Parameters:
- * image (I) - pointer to an allocated image structure.
- * fd (I) - file descriptor of image file.
- * fname (I) - name of image file or NULL.
- *
- * Return: none
- *
- **************************************************************************/
-
- static void errorCleanup(IMPImage *image, int fd, const char *fname)
- {
- /*
- * Close the image file if we opened it and it is valid
- */
- if (fname && (fd >= 0))
- (void)close(fd);
-
- /*
- * Free the allocated image structure fields and the
- * image structure itself
- */
- if (image->rowstart)
- free(image->rowstart);
- if (image->rowsize)
- free(image->rowsize);
- if (image->tmpbuf)
- free(image->tmpbuf);
- free(image);
- }
-
-
- /**************************************************************************
- *
- * Function: readData
- *
- * Description: A wrapper around the read function that allows us to
- * specify an offset from the beginning of the file.
- *
- * Parameters:
- * fd (I) - file descriptor from which to read
- * fromBuf (I) - if not NULL this buffer will be read instead of fd
- * toBuf (I) - buffer to fill with read data
- * amount (I) - number of bytes to read
- * offset (I) - offset from beginning of file where data is to be read.
- *
- * Return: Number of bytes read if no error or -1 if error.
- *
- **************************************************************************/
-
- static int readData(int fd, void *fromBuf, void *toBuf,
- unsigned int amount, off_t offset)
- {
- if (fromBuf) {
- memcpy(toBuf, &((char*)fromBuf)[offset], amount);
- return (int)amount;
- }
-
- if (lseek(fd, offset, SEEK_SET) == -1)
- return -1;
- return read(fd, toBuf, amount);
- }
-
-
- /**************************************************************************
- *
- * Function: writeData
- *
- * Description: A wrapper around the write function that allows us to
- * specify an offset from the beginning of the file.
- *
- * Parameters:
- * fd (I) - file descriptor from which to read
- * fromBuf (I) - buffer to write
- * amount (I) - number of bytes to write
- * offset (I) - offset from beginning of file where data is to be written.
- *
- * Return: Number of bytes written if no error or -1 if error.
- *
- **************************************************************************/
-
- static int writeData(int fd, void *fromBuf, unsigned int amount, off_t offset)
- {
- if (lseek(fd, offset, SEEK_SET) == -1)
- return -1;
- return write(fd, fromBuf, amount);
- }
-
-
- /**************************************************************************
- *
- * Function: setCacheSize
- *
- * Description: Sets the cache size and offset fields of the specified
- * image structure. For heap cacheing the cache size is calculated
- * as the size of the raw image data. In this case the cache offset
- * is the position of the start of the iamge data (i.e. table start
- * plus size of tables). If we are memory mapping the file the offset
- * is the closest page and the cache size is the amount of raw image
- * data plus the slop due to page alignment.
- *
- * Parameters:
- * image (I) - SGI image structure
- *
- * Return: Size in bytes to store the entire image.
- *
- **************************************************************************/
-
- static void setCacheSize(IMPImage *image)
- {
- /*
- * If the image is RLE compressed, sum the rowsize array to get the
- * total image data size. The offset is the max header size and the
- * size of the tables.
- */
- if (impIsRLE(image)) {
- int i;
- int num = impYSize(image) * impNumChannels(image);
-
- for (i = 0, image->cachesize = 0; i < num; i++)
- image->cachesize += image->rowsize[i];
- image->cacheoffset = image->start + _IMP_TABLES_START +
- 2 * num * sizeof(__int32_t);
- }
- /*
- * Otherwise the image is verbatim and we calculate the size directly
- */
- else {
- image->cachesize = impXSize(image) * impYSize(image) *
- impNumChannels(image) * impRasterBPP(image);
- image->cacheoffset = image->start + _IMP_TABLES_START;
- }
-
- /*
- * If we are memory mapping the file we need to align the cache on
- * a page boundary so we adjust the cache offset and size accordingly.
- */
- if (image->cache == IMPMapCache) {
- int adjust = image->cacheoffset % getpagesize();
- image->cachesize += adjust;
- image->cacheoffset -= adjust;
- }
- }
-
-
- /**************************************************************************
- *
- * Function: getTags
- *
- * Description: Reads any extension tags that are appended to the image.
- * If tags are present, the image structure is intialized to
- * point to them.
- *
- * Parameters:
- * image (I) - SGI image structure
- * fd (I) - image file descriptor
- * buf (I) - image buffer
- * offset (I) - start of image data on file
- * offsetTags (I) - where the tags begin
- *
- * Return: nothing
- *
- **************************************************************************/
-
- static void getTags(IMPImage *image, int fd, void *buf, off_t offset,
- __uint32_t offsetTags)
- {
- IMPTag dummyTag;
- char test[4];
- char *magic="tags";
- off_t localOffset;
-
- localOffset = offset + offsetTags;
- if(readData(fd, buf, &dummyTag.header, sizeof(IMPTagHeader),
- localOffset) != sizeof(IMPTagHeader))
- return;
- localOffset += sizeof(IMPTagHeader);
- if(readData(fd, buf, test, 4, localOffset) != 4)
- return;
- localOffset += 4;
- if(image->dorev) {
- _impSwapLongs((__uint32_t *) &dummyTag.header,
- sizeof(IMPTagHeader));
- _impSwapLongs((__uint32_t *) test, 1);
- }
-
- if( (dummyTag.header.tagname != IMP_TAG_FIRST_TAG) ||
- (dummyTag.header.length != strlen(magic)) ||
- strncmp(test, magic, 4) != 0) {
- /* We don't actually have any extension tags */
- impTags(image) = (IMPTag *) 0;
- } else {
- IMPTag **prevTagPtr, *pTag;
-
- prevTagPtr = &image->tags;
- pTag = malloc(sizeof(IMPTag));
- if(readData(fd, buf, &pTag->header, sizeof(IMPTagHeader),
- localOffset) != sizeof(IMPTagHeader))
- return;
- /* XXX is there a byte swapping problem here? */
- localOffset += sizeof(IMPTagHeader);
-
- while(pTag->header.tagname != IMP_TAG_LAST_TAG) {
- pTag->data = malloc(pTag->header.length);
- *prevTagPtr = pTag;
- if(readData(fd, buf, pTag->data, pTag->header.length, localOffset)
- != pTag->header.length)
- return;
- localOffset += pTag->header.length;
- prevTagPtr = &pTag->next;
- pTag = malloc(sizeof(IMPTag));
- if(readData(fd, buf, pTag, sizeof(IMPTagHeader), localOffset) !=
- sizeof(IMPTagHeader))
- return;
- localOffset += sizeof(IMPTagHeader);
- }
- /* We don't actually want to save the final null pointer */
- *prevTagPtr = (IMPTag *) NULL;
- free(pTag);
- }
- }
-